<template>
  <div>
    <!-- Grid toolbar Button describe
      按钮操作类型一般分为两类
      一类是针对表内数据的数据操作（简单的数据删除及修改）
      二类是根据选择的表格的数据进行页面操作
      三类是无数据类的页面操作（一般为新增数据）
     -->
    <!--Grid toolbar Button start  -->
    <div class="k-grid-toolbar-header">
      <k-button v-for="(item,index) in toolbar" :key="index" :icon="item.icon" :class="item.class" style="margin-bottom:5px" @click="toolbarBtnclick(item)">
        {{ item.text }}
      </k-button>
    </div>
    <!--Grid toolbar Button end  -->
    <div class="k-grid-body">
      <kendo-grid
        v-if="option.remoteData"
        :ref="isEmpty(option.ref)?'grid':option.ref"
        :data-source-ref="isEmpty(option.dataSourceRef)?'dataSource':option.dataSourceRef"
        :groupable="true"
        :editable="option.editable"
        :sortable="option.sortable"
        :reorderable="option.reorderable"
        :resizable="option.resizable"
        :filterable="option.filterable"
        :toolbar="option.toolbar"
        :excel-export="option.toolbar?(option.excel.export?option.excel.export:excelExport):null"
        :excel-file-name="option.toolbar?option.excel.fileName:''"
        :excel-all-pages="option.toolbar?option.excel.allPages:false"
        :pdf-all-pages="true"
        :pdf-file-name="option.toolbar?option.excel.fileName:''"
        :pageable="option.pageable"
        :pageable-refresh="true"
        :pageable-button-count="5"
        :column-menu="true"
        :selectable="option.selectSingle"
        :persist-selection="true"
        :cell-render="option.cellRender"
        :change="onChange"
      >
        <kendo-datasource
          :ref="isEmpty(option.dataSourceRef)?'dataSource':option.dataSourceRef"
          :type="tableGridDataSourceOption.type"
          :page-size="tableGridDataSourceOption.pageSize"
          :transport-read-type="'POST'"
          :transport-read-url="tableGridDataSourceOption.transportReadUrl"
          :transport-read-data-type="tableGridDataSourceOption.type"
          :transport-update-type="'POST'"
          :transport-update-url="tableGridDataSourceOption.transportUpdateUrl"
          :transport-update-data-type="tableGridDataSourceOption.type"
          :transport-destroy-type="'POST'"
          :transport-destroy-url="tableGridDataSourceOption.transportDestroyUrl"
          :transport-destroy-data-type="tableGridDataSourceOption.type"
          :transport-create-type="'POST'"
          :transport-create-url="tableGridDataSourceOption.transportCreateUrl"
          :transport-create-data-type="tableGridDataSourceOption.type"
          :transport-parameter-map="tableGridDataSourceOption.parameterMap===undefined?parameterMap:tableGridDataSourceOption.parameterMap"
          :server-paging="true"
          :request-end="requestEnd"
          :schema-model-id="tableGridDataSourceOption.schema.model.id"
          :schema-model-fields="tableGridDataSourceOption.schema.model.fields"
          :schema-data="tableGridDataSourceOption.schema.data"
          :schema-total="tableGridDataSourceOption.schema.total"
          :group="tableGridDataSourceOption.group"
          :aggregate="tableGridDataSourceOption.aggregate"
          :batch="tableGridDataSourceOption.batch"
        />
        <kendo-grid-column v-if="option.selectMultiple" :selectable="true" :width="40" :locked="true" />
        <kendo-grid-column
          v-for="(item,index) in option.columns"
          :key="index"
          :header-attributes="{style:'font-weight:500'}"
          :field="item.field"
          :title="item.title"
          :locked="item.locked"
          :width="item.width"
          :format="item.format"
          :aggregates="item.aggregates"
          :group-footer-template="item.groupFooterTemplate"
          :editor="item.editor"
          :template="isEmpty(item.template)?function(e){
            if(Object.keys(e).length>0){
              if (item && item.dictData) {
                if(dictionary){
                  const dictData = dictionary[item.dictData]
                  if (dictData && dictData.length > 0) {
                    const valsArr = isEmpty(e[item.field])?[]:e[item.field].split(',')
                    const newValsArr = []
                    if(valsArr.length>0){
                      valsArr.forEach(val=>{
                        const newItem = dictData.filter(i => i.dictVal === val)
                        if(newItem.length > 0){
                          newValsArr.push(newItem[0]['dictValNm'])
                        }
                      })
                      return newValsArr.join(',')
                    }else{
                      return isEmpty(e[item.field])?'': e[item.field]
                    }
                  } else {
                    return isEmpty(e[item.field])?'': e[item.field]
                  }
                }else{
                  return isEmpty(e[item.field])?'': e[item.field]
                }
              } else {
                if(item.format){
                  return kendoFormat(item.format,e[item.field])
                }else{
                  return isEmpty(e[item.field])?'': e[item.field]
                }
              }
            }else{
              return '#:'+item.field+'#'
            }
          }:item.template"
        />
        <kendo-grid-column
          v-if="option.editable==='inline'"
          :command="['edit', 'destroy']"
          :title="'&nbsp;'"
          :width="180"
        />
      </kendo-grid>
      <kendo-grid
        v-if="!option.remoteData"
        :ref="option.ref"
        :data-source="option.dataSource"
        :sortable="option.sortable"
        :reorderable="option.reorderable"
        :resizable="option.resizable"
        :pageable="option.pageable"
        :pageable-refresh="option.pageableRefresh"
        :pageable-button-count="5"
        :selectable="option.selectSingle"
      >
        <kendo-grid-column v-if="option.selectMultiple" :selectable="true" :width="40" />
        <kendo-grid-column
          v-for="(item,index) in option.columns"
          :key="index"
          :header-attributes="{style:'font-weight:500'}"
          :field="item.field"
          :title="item.title"
          :width="item.width"
          :format="item.format"
          :editor="item.editor"
          :template="item.template"
        />
      </kendo-grid>
    </div>
    <KendoWindow
      :dialog-title="dialogTitle"
      :components-list="componentsList"
      :operate-dialog-view="operateDialogView"
      @beforeClose="beforeClose"
    />
  </div>
</template>

<script>
  // eslint-disable-next-line no-undef
  import JSZip from 'jszip'
  window.JSZip = JSZip
  import { Button } from '@progress/kendo-buttons-vue-wrapper'
  export default {
    name: 'KendoGridCmpt',
    components: {
      'k-button': Button
    },
    props: {
      tableGridOption: {
        type: Object,
        default() {
          return {}
        }
      },
      tableGridDataSourceOption: {
        type: Object,
        default() {
          return {}
        }
      },
      tableGridToolbar: {
        type: Array,
        default() {
          return []
        }
      }
    },
    data() {
      return {
        /* window-start*/
        dialogTitle: '',
        dialogName: this.uid(),
        componentsList: [],
        operateDialogView: false,
        /* window-end*/
        option: {},
        dictionary: {},
        dataSourceOption: {},
        toolbar: [],
        persistSelection: [],
        loadedRemoteDictData: false
      }
    },
    watch: {
      loadedRemoteDictData: {
        immediate: true,
        handler() {
          if (this.loadedRemoteDictData) {
            this.option = this.tableGridOption
            this.toolbar = this.tableGridToolbar ? this.tableGridToolbar : []
            this.dataSourceOption = this.tableGridDataSourceOption
          }
        }
      }
    },
    created() {
      this.$bus.on('dialog' + this.dialogName, (resData) => {
        if (resData) {
          this.beforeClose(resData)
        }
      })
    },
    beforeDestroy() {
      this.$bus.off('dialog' + this.dialogName)
    },
    mounted() {
      this.initDict().then(_ => {

      })
    },
    methods: {
      async initDict() {
        // 获取字典数据
        const DICT = this.tableGridDataSourceOption.dict
        const REMOTE_TRANS_DATA = this.tableGridDataSourceOption.remoteTransData
        const transportParam = {
          dict: DICT
        }
        await this.$post('/service/sysMng/dict/findDictByTypeWithGrid', transportParam).then(res => {
          if (res.code !== 200) {
            this.$KendoNotify({
              title: '错误信息:' + res.data.code,
              message: res.data.message
            }, 'error')
          } else {
            this.dictionary = res.data
            this.$post('/service/sysMng/dict/findDictWithRemoteData', REMOTE_TRANS_DATA).then(_res => {
              this.dictionary = Object.assign(this.dictionary, _res.data)
              this.loadedRemoteDictData = true
            })
          }
        })
      },
      async loadRemoteDictData(key, request) {
        const transportReadUrl = request.transportReadUrl
        const transportParam = request.transportParam
        await this.$post(transportReadUrl, transportParam).then(res => {
          if (res && res.code === 200) {
            const dataList = res.data
            this.$set(this.dictionary, key, dataList)
          } else {
            this.$KendoNotify({
              title: '错误信息:' + res.code,
              message: res.message
            }, 'error')
          }
        })
      },
      requestEnd(e) {
        const gridRef = this.$refs[this.tableGridOption.ref]
        let grid
        if (gridRef) {
          grid = this.$refs[this.tableGridOption.ref].kendoWidget()
        }
        if (e.type !== 'read') {
          grid.dataSource.read()
        } else {
          grid.clearSelection()
          this.persistSelection = []
        }
      },
      parameterMap(options, operation) {
        if (operation !== 'read' && options.models) {
          // eslint-disable-next-line no-undef
          return { parameterMap: kendo.stringify(options.models) }
        } else {
          const parameterMap = this.dataSourceOption.params
          parameterMap.pageNum = options.page
          parameterMap.pageSize = options.pageSize
          // eslint-disable-next-line no-undef
          return kendo.stringify(parameterMap)
        }
      },
      transportReadGrid() {
        const REMOTE_TRANS_DATA = this.tableGridDataSourceOption.remoteTransData
        var grid = this.$refs[this.tableGridOption.ref].kendoWidget()
        if (!this.loadedRemoteDictData) {
          this.$post('/service/sysMng/dict/findDictWithRemoteData', REMOTE_TRANS_DATA).then(_res => {
            this.dictionary = Object.assign(this.dictionary, _res.data)
            this.loadedRemoteDictData = true
            grid.dataSource.read()
          })
        } else {
          grid.dataSource.read()
        }
      },
      // 选择表格方法，获取已选择表格的数据并发送到父组件
      onChange(ev) {
        const _that = this
        const _this = ev.sender
        const selectDataItems = []
        const schemaId = _this.dataSource.options.schema.model.id
        const selected = _this.selectedKeyNames()
        const dataItems = _this.dataItems()
        if (selected.length > 0) {
          selected.forEach(element => {
            const item = dataItems.filter(s => s[schemaId] === element)
            if (item.length > 0) {
              if (item.length === 1) {
                selectDataItems.push(...item)
              } else {
                selectDataItems.push(item[0])
              }
            }
          })
        }
        _that.persistSelection = selectDataItems
        _that.$emit('persistSelection', selectDataItems)
      },
      // 预处理表格操作按钮的点击事件
      toolbarBtnclick(item) {
        const EDIT = 'edit'; const VIEW = 'view'
        // 获取操作类型
        const operatorType = item.operatorType
        // 获取操作配置
        const option = item.option
        // 根据操作配置判定当前操作模式
        // 数据操作，请求后台处理
        if (option.model === 'dataReq') {
          if (this.persistSelection && this.persistSelection.length > 0) {
            this.$kendoConfirm({
              title: '提示消息',
              message: '是否确认当前操作！',
              btn: [
                {
                  type: 'submit',
                  text: '确定'
                },
                {
                  type: 'cancel',
                  text: '取消'
                }
              ]
            }).then(_ => {
              let parameterMap = option.parameterMap
              if (this.persistSelection.length === 1) {
                parameterMap = Object.assign(parameterMap, this.deepCopy(this.persistSelection[0]))
              } else {
                this.$set(parameterMap, 'dataItems', this.persistSelection)
              }
              this.$post(option.transportRequestUrl, parameterMap).then(res => {
                if (res && res.code === 200) {
                  this.transportReadGrid()
                } else {
                  this.$KendoNotify({
                    title: '错误信息:' + res.code,
                    message: res.message
                  }, 'error')
                }
              })
            }).catch(_ => {

            })
          } else {
            this.$KendoNotify({
              title: '警告',
              message: '请选择一条数据信息!'
            }, 'warning')
          }
        } else if (option.model === 'export') {
          if (this.persistSelection && this.persistSelection.length > 0) {
            let parameterMap = option.parameterMap
            if (this.persistSelection.length === 1) {
              this.$kendoConfirm({
                title: '提示消息',
                message: '是否确认当前操作！',
                btn: [
                  {
                    type: 'submit',
                    text: '确定'
                  },
                  {
                    type: 'cancel',
                    text: '取消'
                  }
                ]
              }).then(_ => {
                parameterMap = Object.assign(parameterMap, this.deepCopy(this.persistSelection[0]))
                this.$exportpost(option.transportRequestUrl, parameterMap, 'blob').then(res => {
                  if (!res) {
                    return
                  }
                  if (window.navigator.msSaveBlob) { // IE以及IE内核的浏览器
                    try {
                      window.navigator.msSaveBlob(res, parameterMap.fileName) // res为接口返回数据，这里请求的时候已经处理了，如果没处理需要在此之前自行处理
                      // window.navigator.msSaveOrOpenBlob(res, fileName);  //此方法类似上面的方法，区别可自行百度
                    } catch (e) {
                      console.log(e)
                    }
                  } else {
                    const url = window.URL.createObjectURL(new Blob([res.data]))
                    const link = document.createElement('a')
                    link.style.display = 'none'
                    link.href = url
                    link.setAttribute('download', parameterMap.fileName)// 文件名
                    document.body.appendChild(link)
                    link.click()
                    document.body.removeChild(link) // 下载完成移除元素
                    window.URL.revokeObjectURL(url) // 释放掉blob对象
                  }
                })
              }).catch(_ => {

              })
            } else {
              this.$KendoNotify({
                title: '警告',
                message: '请选择一条数据信息!'
              }, 'warning')
            }
          } else {
            this.$KendoNotify({
              title: '警告',
              message: '请选择一条数据信息。'
            }, 'warning')
          }
        } else if (option.model === 'dataView') {
          // 如果是新增
          if (operatorType === EDIT || operatorType === VIEW) {
            // 校验当前选中数据是否为一条数据
            if (this.persistSelection.length && this.persistSelection.length > 0 && this.persistSelection.length === 1) {
              // 获取当前新增页面路径
              const component = {
                component: option.componentUrl,
                dialogName: this.dialogName,
                operatorType: operatorType,
                param: Object.assign(option.parameterMap, this.deepCopy(this.persistSelection[0]))
              }
              this.operateDialogView = true
              this.dialogTitle = option.dialogTitle
              this.componentsList.push(component)
            } else {
              this.$KendoNotify({
                title: '警告',
                message: '请选择一条数据信息。'
              }, 'warning')
            }
          } else {
            // 获取当前新增页面路径
            const component = {
              component: option.componentUrl,
              dialogName: this.dialogName,
              operatorType: operatorType,
              param: option.parameterMap
            }
            this.operateDialogView = true
            this.dialogTitle = option.dialogTitle
            this.componentsList.push(component)
          }
        }
      },
      isEmpty(str) {
        if (str == null || typeof str === 'undefined' || str === '') {
          return true
        }
        return false
      },
      kendoFormat(format, value) {
        // eslint-disable-next-line no-undef
        kendo.culture('zh-CN')
        // eslint-disable-next-line no-undef
        return kendo.format(format, value)
      },
      beforeClose(res) {
        if (res) {
          this.dialogTitle = ''
          this.operateDialogView = false
          this.componentsList = []
          this.transportReadGrid()
        }
      },
      excelExport(e) {
        const dataConversionCol = []
        const newArr = []
        const arr = this.recursive(e.data, newArr)
        if (arr.length !== e.data.length) {
          const lastItem = arr[arr.length - 1]
          arr.splice(arr.length - 1, 1)
          arr.unshift(lastItem)
        } else {
          arr.unshift([])
        }
        this.option.columns.forEach(item => {
          if (item.dictData) {
            dataConversionCol.push({ paramName: item.field, type: 'dictData', dictData: item.dictData })
          } else if (item.format) {
            dataConversionCol.push({ paramName: item.field, type: 'format', format: item.format })
          }
        })
        arr.forEach((element, index) => {
          const columns = e.sender.columns.filter(s => s.field && s.field !== null && s.field !== '')
          const selectIndex = columns.map(s => s.selectable).indexOf(true)
          if (selectIndex >= 0) {
            columns.splice(selectIndex, 1)
          }
          dataConversionCol.forEach(item => {
            const i = columns.map(s => s.field).indexOf(item.paramName)
            if (item.type === 'dictData') {
              let valsArr = []
              if (element[item.paramName] !== undefined && element[item.paramName] !== null) {
                valsArr = element[item.paramName].split(',')
              }
              const newValsArr = []
              if (valsArr.length > 0) {
                valsArr.forEach(val => {
                  const newItem = this.dictionary[item.dictData].filter(o => o.dictVal === val)
                  if (newItem.length > 0) {
                    newValsArr.push(newItem[0]['dictValNm'])
                  }
                })
                const row = e.workbook.sheets[0].rows[index]
                const cellsLenth = e.workbook.sheets[0].rows[index].cells.length
                const columnsLenth = columns.length
                const i_ = i + cellsLenth - columnsLenth
                if (row.type === 'data') {
                  e.workbook.sheets[0].rows[index].cells[i_].value = newValsArr.join(',')
                }
              }
            } else if (item.type === 'format') {
              const row = e.workbook.sheets[0].rows[index]
              const cellsLenth = e.workbook.sheets[0].rows[index].cells.length
              const columnsLenth = columns.length
              const i_ = i + cellsLenth - columnsLenth
              if (row.type === 'data') {
                e.workbook.sheets[0].rows[index].cells[i_].value = this.kendoFormat(item.format, element[item.paramName])
              }
            }
          })
        })
      },
      recursive(dataArr, newArr) {
        dataArr.forEach(dataItem => {
          if (dataItem.items && dataItem.items.length > 0) {
            const items = dataItem.items
            delete dataItem.items
            newArr.push(dataItem)
            return this.recursive(items, newArr)
          } else {
            newArr.push(dataItem)
          }
        })
        if (this.tableGridDataSourceOption.group) {
          newArr.push({})
        }
        return newArr
      },
      detailInit(e) {
        // eslint-disable-next-line no-undef
        kendo.jQuery('<div />').appendTo(e.detailCell).kendoGrid({
          dataSource: {
            type: 'odata',
            transport: {
              read: 'https://demos.telerik.com/kendo-ui/service/Northwind.svc/Orders'
            },
            serverPaging: true,
            serverSorting: true,
            serverFiltering: true,
            pageSize: 10,
            filter: {
              field: 'EmployeeID',
              operator: 'eq',
              value: e.data.EmployeeID
            }
          },
          scrollable: false,
          sortable: true,
          pageable: true,
          columns: [{
                      field: 'OrderID',
                      width: '110px'
                    },
                    {
                      field: 'ShipCountry',
                      title: 'Ship Country',
                      width: '110px'
                    },
                    {
                      field: 'ShipAddress',
                      title: 'Ship Address'
                    },
                    {
                      field: 'ShipName',
                      title: 'Ship Name',
                      width: '300px'
                    }]
        })
      }
    }
  }
  // eslint-disable-next-line no-undef
  kendo.pdf.defineFont({
    'DejaVu Sans': 'src/Styles/iconfont/DejaVuSans.ttf',
    'DejaVu Sans|Bold': 'src/Styles/iconfont/DejaVuSans.ttf'
  })
</script>

<style>
  .k-grid-toolbar-header>button:not(:first-child){
    margin-left: 3px;
  }
    .k-widget {
        font-family: "DejaVu Sans", "Arial", sans-serif;
        font-size: .9em;
    }
</style>
